// Kokomi.js - Three.js 组件框架
import * as kokomi from "kokomi.js";
// Three.js - 3D 渲染引擎
import * as THREE from "three";
// GSAP - 动画库
import gsap from "gsap";

import type Experience from "../Experience";

// 动态环境的自定义着色器
import dynamicEnvVertexShader from "../Shaders/DynamicEnv/vert.glsl";
import dynamicEnvFragmentShader from "../Shaders/DynamicEnv/frag.glsl";

// 动态环境配置接口
export interface DynamicEnvConfig {
  envmap1: THREE.Texture; // 环境贴图1（夜间环境）
  envmap2: THREE.Texture; // 环境贴图2（明亮环境）
}

// GSAP 时间轴，用于平滑过渡环境权重
const t1 = gsap.timeline();

/**
 * 动态环境组件
 * 用于在两个环境贴图之间进行平滑过渡（夜间 ↔ 明亮）
 * 使用 FBO（Frame Buffer Object）离屏渲染混合后的环境贴图
 */
export default class DynamicEnv extends kokomi.Component {
  declare base: Experience; // Experience 实例引用
  fbo: kokomi.FBO; // 帧缓冲对象，用于离屏渲染
  material: THREE.ShaderMaterial; // 自定义着色器材质
  quad: kokomi.FullScreenQuad; // 全屏四边形，用于渲染到 FBO
  
  constructor(base: Experience, config: Partial<DynamicEnvConfig> = {}) {
    super(base);

    // 从配置中获取两个环境贴图
    const { envmap1, envmap2 } = config;

    // 获取环境贴图的原始数据（用于设置 FBO 分辨率）
    const envData = envmap1?.source.data;

    // 创建帧缓冲对象，匹配环境贴图的分辨率
    const fbo = new kokomi.FBO(this.base, {
      width: envData.width,
      height: envData.height,
    });
    this.fbo = fbo;

    // 设置环境贴图映射方式为立方体 UV 反射映射
    this.envmap.mapping = THREE.CubeUVReflectionMapping;

    // 创建自定义着色器材质，用于混合两个环境贴图
    const material = new THREE.ShaderMaterial({
      vertexShader: dynamicEnvVertexShader,
      fragmentShader: dynamicEnvFragmentShader,
      uniforms: {
        uEnvmap1: {
          value: envmap1, // 环境贴图1（夜间）
        },
        uEnvmap2: {
          value: envmap2, // 环境贴图2（明亮）
        },
        uWeight: {
          value: 0, // 混合权重（0=完全使用贴图1，1=完全使用贴图2）
        },
        uIntensity: {
          value: 1, // 环境光强度
        },
      },
    });
    this.material = material;

    // 创建全屏四边形用于渲染
    const quad = new kokomi.FullScreenQuad(material);
    this.quad = quad;
  }
  /**
   * 每帧更新，将混合后的环境贴图渲染到 FBO
   */
  update() {
    // 设置渲染目标为 FBO（离屏渲染）
    this.base.renderer.setRenderTarget(this.fbo.rt);
    // 渲染全屏四边形（执行着色器混合）
    this.quad.render(this.base.renderer);
    // 恢复渲染目标为屏幕
    this.base.renderer.setRenderTarget(null);
  }
  /**
   * 获取混合后的环境贴图
   * 供场景使用作为环境光
   */
  get envmap() {
    return this.fbo.rt.texture;
  }
  /**
   * 设置环境贴图混合权重
   * @param value - 0=夜间环境，1=明亮环境
   */
  setWeight(value: number) {
    this.material.uniforms.uWeight.value = value;
  }
  /**
   * 设置环境光强度
   * @param value - 强度值（0-1）
   */
  setIntensity(value: number) {
    this.material.uniforms.uIntensity.value = value;
  }
  /**
   * 平滑过渡到目标权重
   * @param value - 目标权重值
   * @param duration - 过渡时长（秒）
   */
  lerpWeight(value: number, duration: number) {
    // t1.timeScale(0.2); // 可选：调整时间缩放
    t1.to(this.material.uniforms.uWeight, {
      value,
      duration,
      ease: "power2.out",
    });
  }
}
